/****************************************************
 * 创建人：@author fengxin    
 * 创建时间: 2019/7/11/14:48
 * 项目名称: AkkaLearn
 * 文件名称: ActorHierarchyExperiments.java
 * 文件描述: @Description: actor hierarchy
 * 公司名称: 深圳市赢和信息技术有限公司
 * All rights Reserved, Designed By 深圳市赢和信息技术有限公司
 * @Copyright:2019-2019
 *
 ********************************************************/


package com.example.arhitecture;

/**
 * 包名称：ActorHierarchy
 * 类名称：ActorHierarchyExperiments
 * 类描述：actor hierarchy
 * 创建人：@author fengxin
 * 创建时间：2019/7/11/14:48
 */

import akka.actor.*;

class PrintMyActorRefActor extends AbstractActor {
    static Props props() {
        return Props.create(PrintMyActorRefActor.class, PrintMyActorRefActor::new);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .matchEquals(
                        "printit",
                        p -> {
                            ActorRef secondRef = getContext().actorOf(Props.empty(), "second-actor");
                            System.out.println("Second: " + secondRef);
                        })
                .build();
    }
}



class HelloActor extends AbstractActor {
    static Props props() {
        return Props.create(HelloActor.class, HelloActor::new);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .matchEquals(
                        "printFree",
                        p -> {
System.out.println("freedom is worthless.");
                        })
                .build();
    }
}



class StartStopActor1 extends AbstractActor {
    static Props props() {
        return Props.create(StartStopActor1.class, StartStopActor1::new);
    }

    @Override
    public void preStart() {
        System.out.println("first started");
        getContext().actorOf(StartStopActor2.props(), "second");
    }

    @Override
    public void postStop() {
        System.out.println("first stopped");
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .matchEquals(
                        "stop",
                        s -> {
                            getContext().stop(getSelf());
                        })
                .build();
    }
}

class StartStopActor2 extends AbstractActor {

    static Props props() {
        return Props.create(StartStopActor2.class, StartStopActor2::new);
    }

    @Override
    public void preStart() {
        System.out.println("second started");
    }

    @Override
    public void postStop() {
        System.out.println("second stopped");
    }

    // Actor.emptyBehavior is a useful placeholder when we don't
    // want to handle any messages in the actor.
    @Override
    public Receive createReceive() {
        return receiveBuilder().build();
    }
}

class SupervisingActor extends AbstractActor {
    static Props props() {
        return Props.create(SupervisingActor.class, SupervisingActor::new);
    }

    ActorRef child = getContext().actorOf(SupervisedActor.props(), "supervised-actor");

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .matchEquals(
                        "failChild",
                        f -> {
                            child.tell("fail", getSelf());
                        })
                .build();
    }
}

class SupervisedActor extends AbstractActor {
    static Props props() {
        return Props.create(SupervisedActor.class, SupervisedActor::new);
    }

    @Override
    public void preStart() {
        System.out.println("supervised actor started");
    }

    @Override
    public void postStop() {
        System.out.println("supervised actor stopped");
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .matchEquals(
                        "fail",
                        f -> {
                            System.out.println("supervised actor fails now");
                            throw new Exception("I failed!");
                        })
                .build();
    }
}

public class ActorHierarchyExperiments  {
    static ActorSystem system = ActorSystem.create("testSystem");

    public static void printRef() throws Exception {


        ActorRef firstRef = system.actorOf(PrintMyActorRefActor.props(), "first-actor");

        ActorRef helloRef =system.actorOf(HelloActor.props(),"hello-actor");

        ActorPath helloPath =  helloRef.path();
        //System.out.println(helloPath);

       // ActorSelection helloSelection =
       //         system.actorSelection(helloPath);

       /// helloSelection.tell("printFree",ActorRef.noSender());
        //helloRef.tell(new PoisonPill(){},ActorRef.noSender());

      //  System.out.println(helloRef);

        //helloRef.tell("printFree",ActorRef.noSender());

        System.out.println("First: " + firstRef);
        firstRef.tell("printit", ActorRef.noSender());



    }

    public static void stop() throws Exception {
        ActorRef first = system.actorOf(StartStopActor1.props(), "first");
        first.tell("stop", ActorRef.noSender());
    }

    public static void failureHandle() {
        ActorRef supervisingActor = system.actorOf(SupervisingActor.props(), "supervising-actor");
        supervisingActor.tell("failChild", ActorRef.noSender());
    }

    public static void main(String[] args)  {

        //printRef();
       // stop();
        failureHandle();
    }
}